<!DOCTYPE html>
<!-- saved from url=(0127)https://docs.google.com/document/d/e/2PACX-1vQsDWpQDyZ6rQpoFfvl2wRQUSgiweU_a65yetDj43owzYf_xcZO1Bjt2OEfejLJmj7VKgupNBjM7IRf/pub -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>WebPerfWG call - April 29th 2021</title><link rel="shortcut icon" href="https://ssl.gstatic.com/docs/documents/images/kix-favicon7.ico"><meta name="referrer" content="strict-origin-when-cross-origin"><style type="text/css" nonce="">
      @import url("https://fonts.googleapis.com/css?family=Google+Sans");
      @import url("https://fonts.googleapis.com/css?family=Roboto");

      body {
        font-family: Roboto, arial, sans, sans-serif;
        margin: 0;
      }

      iframe {
        border: 0;
        frameborder: 0;
        height: 100%;
        width: 100%;
      }

      #header {
        align-items: center;
        background: white;
        border-bottom: 1px #ccc solid;
        display: flex;
        height: 60px;
        justify-content: space-between;
        position: fixed;
        top: 0;
        width: 100%;
        z-index: 100;
      }

      #header #title {
        font-family: 'Google Sans';
        font-size: large;
        margin: auto 0 auto 20px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
        width: 70%;
      }

      #header #interval {
        margin: auto 25px auto 0;
        font-family: Roboto;
        font-size: small;;
      }

      #footer {
        background: #f0f0f0;
        border-bottom: 1px #ccc solid;
        bottom: 0;
        font-family: Roboto;
        font-size: small;
        padding: 10px 10px;
        position: fixed;
        text-align: center;
        width: 100%;
      }

      #contents {
        padding: 100px 20% 50px 20%;
      }

      @media only screen and (max-device-width: 800px) {
        #header {
          border-bottom-width: 5px;
          height: auto;
          display: block;
        }

        #header #title {
          font-size: 3em;
          margin: auto 0 auto 20px;
          width: 90%;
        }

        #header #interval {
          font-size: 1.5em;
          margin: 10px 0 auto 25px;
        }

        #contents {
          padding: 150px 5% 80px;
        }

        #footer {
          font-size: 2em;
        }
      }

      .dash {
        padding: 0 6px;
      }
    </style></head><body><div id="header"><div id="title">WebPerfWG call - April 29th 2021</div><div id="interval"><span></span></div></div><div id="contents"><style type="text/css">ul.lst-kix_b1qr3pe9lkq6-8{list-style-type:none}.lst-kix_b1qr3pe9lkq6-8>li:before{content:"\0025a0  "}ul.lst-kix_b1qr3pe9lkq6-4{list-style-type:none}ul.lst-kix_b1qr3pe9lkq6-5{list-style-type:none}.lst-kix_b1qr3pe9lkq6-7>li:before{content:"\0025cb  "}ul.lst-kix_b1qr3pe9lkq6-6{list-style-type:none}ul.lst-kix_b1qr3pe9lkq6-7{list-style-type:none}ul.lst-kix_b1qr3pe9lkq6-0{list-style-type:none}ul.lst-kix_b1qr3pe9lkq6-1{list-style-type:none}.lst-kix_b1qr3pe9lkq6-4>li:before{content:"\0025cb  "}.lst-kix_b1qr3pe9lkq6-5>li:before{content:"\0025a0  "}ul.lst-kix_b1qr3pe9lkq6-2{list-style-type:none}ul.lst-kix_b1qr3pe9lkq6-3{list-style-type:none}.lst-kix_mpohddwg7kmz-3>li:before{content:"\0025cf  "}.lst-kix_b1qr3pe9lkq6-6>li:before{content:"\0025cf  "}.lst-kix_mpohddwg7kmz-4>li:before{content:"\0025cb  "}.lst-kix_b1qr3pe9lkq6-1>li:before{content:"\0025cb  "}.lst-kix_mpohddwg7kmz-5>li:before{content:"\0025a0  "}.lst-kix_b1qr3pe9lkq6-3>li:before{content:"\0025cf  "}.lst-kix_b1qr3pe9lkq6-0>li:before{content:"\0025cf  "}.lst-kix_mpohddwg7kmz-6>li:before{content:"\0025cf  "}.lst-kix_mpohddwg7kmz-7>li:before{content:"\0025cb  "}.lst-kix_b1qr3pe9lkq6-2>li:before{content:"\0025a0  "}.lst-kix_mpohddwg7kmz-8>li:before{content:"\0025a0  "}ul.lst-kix_mpohddwg7kmz-8{list-style-type:none}ul.lst-kix_mpohddwg7kmz-4{list-style-type:none}ul.lst-kix_mpohddwg7kmz-5{list-style-type:none}li.li-bullet-0:before{margin-left:-18pt;white-space:nowrap;display:inline-block;min-width:18pt}ul.lst-kix_mpohddwg7kmz-6{list-style-type:none}ul.lst-kix_mpohddwg7kmz-7{list-style-type:none}ul.lst-kix_mpohddwg7kmz-0{list-style-type:none}ul.lst-kix_mpohddwg7kmz-1{list-style-type:none}ul.lst-kix_mpohddwg7kmz-2{list-style-type:none}ul.lst-kix_mpohddwg7kmz-3{list-style-type:none}.lst-kix_mpohddwg7kmz-2>li:before{content:"\0025a0  "}.lst-kix_mpohddwg7kmz-1>li:before{content:"\0025cb  "}.lst-kix_mpohddwg7kmz-0>li:before{content:"\0025cf  "}ol{margin:0;padding:0}table td,table th{padding:0}.c5{margin-left:36pt;padding-top:0pt;padding-left:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c0{margin-left:72pt;padding-top:0pt;padding-left:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c4{padding-top:18pt;padding-bottom:6pt;line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.c7{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:16pt;font-family:"Arial";font-style:normal}.c9{padding-top:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left;height:11pt}.c1{color:#000000;font-weight:400;text-decoration:none;vertical-align:baseline;font-size:11pt;font-family:"Arial";font-style:normal}.c11{padding-top:0pt;padding-bottom:0pt;line-height:1.15;orphans:2;widows:2;text-align:left}.c6{text-decoration-skip-ink:none;-webkit-text-decoration-skip:none;color:#1155cc;text-decoration:underline}.c8{background-color:#ffffff;max-width:468pt;padding:72pt 72pt 72pt 72pt}.c3{padding:0;margin:0}.c2{color:inherit;text-decoration:inherit}.c10{margin-left:36pt}.title{padding-top:0pt;color:#000000;font-size:26pt;padding-bottom:3pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}.subtitle{padding-top:0pt;color:#666666;font-size:15pt;padding-bottom:16pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}li{color:#000000;font-size:11pt;font-family:"Arial"}p{margin:0;color:#000000;font-size:11pt;font-family:"Arial"}h1{padding-top:20pt;color:#000000;font-size:20pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h2{padding-top:18pt;color:#000000;font-size:16pt;padding-bottom:6pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h3{padding-top:16pt;color:#434343;font-size:14pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h4{padding-top:14pt;color:#666666;font-size:12pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h5{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;orphans:2;widows:2;text-align:left}h6{padding-top:12pt;color:#666666;font-size:11pt;padding-bottom:4pt;font-family:"Arial";line-height:1.15;page-break-after:avoid;font-style:italic;orphans:2;widows:2;text-align:left}</style><div class="c8"><h2 class="c4" id="h.ouroro5547ct"><span class="c7">Participants</span></h2><p class="c11"><span class="c1">Yoav Weiss, Michal Mocny, Nic Jansma, Giacomo Zecchini, Peter Perlepes, Noam Helfman, Nicol&aacute;s Pe&ntilde;a Moreno, Patrick Hamann, Sean Feng, Steven Bougon, Marcel Duran, Benjamin De Kosnik</span></p><h2 class="c4" id="h.ex4724yzly1"><span class="c7">Minutes</span></h2><h2 class="c4" id="h.vyzrehhfssoo"><span class="c7">Topic</span></h2><ul class="c3 lst-kix_b1qr3pe9lkq6-0 start"><li class="c5 li-bullet-0"><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://github.com/w3c/resource-timing/issues/263&amp;sa=D&amp;source=editors&amp;ust=1620034522430000&amp;usg=AOvVaw10WsLk8PotgOKz6V3C5bLU">Resource initiator information to enable creation of dependency trees</a></span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-1 start"><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: A couple weeks we talked about a proposal to expose render blocking information to RT</span></li><li class="c0 li-bullet-0"><span class="c1">... Another proposal here to enable creation of dependency trees</span></li><li class="c0 li-bullet-0"><span class="c1">... Currently with RT we have initiator type information, which is weird and doesn't provide a ton of information</span></li><li class="c0 li-bullet-0"><span class="c1">... Something that would be useful on top of it would be a specific initiator</span></li><li class="c0 li-bullet-0"><span class="c1">... In dev tools for example, we have a link from a resource to what requested it</span></li><li class="c0 li-bullet-0"><span class="c1">... Even the specific line in the HTML triggered that resource request</span></li><li class="c0 li-bullet-0"><span class="c1">... I don't know if we need line-by-line attribution, but it would be helpful from my perspective to add initiator information that may be alongside some concept of Fetch ID or links to RT entry</span></li><li class="c0 li-bullet-0"><span class="c1">... Which would be able to provide dependency trees from RUM data</span></li><li class="c0 li-bullet-0"><span class="c1">... i.e. Script A triggered Script B to Script C which triggered an image load</span></li><li class="c0 li-bullet-0"><span class="c1">... And if that script or image caused issues, we can go back to Script A to assign blame</span></li><li class="c0 li-bullet-0"><span class="c1">… Whether the author of Script A in on our team or a third party provider.</span></li><li class="c0 li-bullet-0"><span class="c1">… Thoughts? Would that be useful?</span></li><li class="c0 li-bullet-0"><span class="c1">… In the past I thought it can be used to find long dependency chains and then flatten them using preload.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>NoamH </b>: Personally I would find it very helpful</span></li><li class="c0 li-bullet-0"><span class="c1">... Would find it more useful if like dev tools it showed full call tree or stack traces</span></li><li class="c0 li-bullet-0"><span class="c1">... In terms of usefulness for diagnostic or determining issues</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: I think it might be interesting to tie that to JS Profiling proposal in some way</span></li><li class="c0 li-bullet-0"><span class="c1">... When JS Profiling is enabled, maybe we can provide more initiator data</span></li><li class="c0 li-bullet-0"><span class="c1">... I would tie to to same security primitives that JS Profiling has</span></li><li class="c0 li-bullet-0"><span class="c1">... Main difference is that JS Profiling is an opt-in, where initiator is something we'd want to enable for everyone ideally</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: What about when you have a service worker involved and several tabs open requesting resources. &nbsp;How can we organize this mess?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: In this case, we're talking about the render-based initiator or the SW as the initiator?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: The SW would be handling the events, but it would be triggered by something in the page</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: That's a good question</span></li><li class="c0 li-bullet-0"><span class="c1">... I would expect this info would be tied to theRequest object in Fetch, and if the SW generated a new request object, then the SW would become the initiator instead of the original renderer based-one</span></li><li class="c0 li-bullet-0"><span class="c1">… But I’d love for you to be involved in those discussions</span></li><li class="c0 li-bullet-0"><span class="c1">... It'd definitely more complex than "let's add initiator info"</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: Currently with SW, I have enough problems figuring out where a resource came from. Hard to map without ID. ID would help in this case.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Do you know what dev tools in browsers do for this case?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: I'm not sure, when I'm debugging I have dedicated dev tools for this situation</span></li><li class="c0 li-bullet-0"><span class="c1">... Not sure how we'd map one to another</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: If you could outline your use-case in this issue, that’s be great.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Benjamin</b>: Would you consider Preload an initiator, that would be a root?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Yes for Preload, that would be an initiator</span></li><li class="c0 li-bullet-0"><span class="c1">... There's HTML-based Preload, and for that I'd consider the HTML the initiator of that Preload, and tie that back to the link rel=preload tag that kicked it off</span></li><li class="c0 li-bullet-0"><span class="c1">... For HTTP header preloads, I'd consider the resource that triggered the initiator, line-by-line may be hard in that case</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Benjamin</b>: Ideally we'd be able to pick apart where the Preload request came from, any light you could shine on that the better</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Noam</b>: Another use-case: when you have an app w/ 3P resources that you don't, they often initiate requests for resources and it’s hard to troubleshoot. Even though you can see them on RT you don't know where they're coming from</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Very much the use case I had in mind</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: It would be similar to Simon Hearne's RequestMap tool, but doing that from RUM would be great</span></li><li class="c0 li-bullet-0"><span class="c1">.. Akamai’s point of view, this would be useful. &nbsp;From a RUM perspective, we try to do some of this heuristically or when looking at waterfalls for customers. &nbsp;Would love a more definitive answer for what to point to… assigning blame / biggest hitters</span></li><li class="c0 li-bullet-0"><span class="c1">..The edge itself could make more intelligent decisions to deliver content in different ways</span></li><li class="c0 li-bullet-0"><span class="c1">..Security perspective: could you find rogue requests going out? Security products could find things.. what triggered what.. may enable things we haven’t even thought of! &nbsp;As long as we do that in a safe &amp; secure way.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Yeah the security is interesting.. Tied to report-only CSP? Then can tie CSP violations back to the RUM report, and find which 3p was responsible for the request?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: Another point would be with extensions, not knowing which extension a request came from</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: I'm not sure if we can expose scripts from "another world" in that case</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Marcel</b>: If a known resource from a screen-reader for example</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: There may be privacy concerns or from an implementation perspective</span></li><li class="c0 li-bullet-0"><span class="c1">... e.g. an extension is not a "previous resource"</span></li><li class="c0 li-bullet-0"><span class="c1">... Also, going back to security case, I'm not sure we can guarantee to have attribution to the initiator. If a request is initiated during a setTimeout callback, does the browser keep this info? There may be loopholes in the security story</span></li><li class="c0 li-bullet-0"><span class="c1">... But interesting to keep that use case in mind, and see what we can do. Maybe we can only tackle non-sophisticated hackers</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: +1 to the extension case. Customers often ask why resources are triggered, when it can be extensions that don’t reproduce locally. Some attribution there, or even an indication that it was triggered by something outside the page would be helpful. Causes confusion for sure.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Would probably be safe to say “triggered by extension”, but need to verify.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Thanks all for the feedback, I expect there's a lot of value in this that we can unlock</span></li><li class="c0 li-bullet-0"><span>... Critical to figure out use cases and edge cases that could trip us up<br></span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-0"><li class="c5 li-bullet-0"><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://github.com/w3c/resource-timing/issues/271&amp;sa=D&amp;source=editors&amp;ust=1620034522434000&amp;usg=AOvVaw31XBI0sABmotFcqemq5NFn">Reference mess</a></span><span class="c1">&nbsp;</span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-1 start"><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: I'm not sure if this will be actionable on the call</span></li><li class="c0 li-bullet-0"><span class="c1">... We need to setup auto-publishing</span></li><li class="c0 li-bullet-0"><span class="c1">... The Fetch spec currently has references to both RT and RT2</span></li><li class="c0 li-bullet-0"><span class="c1">... New SpecProd Github repo that I need to figure out and deploy, offers a great way to build ReSpec specs to avoid situation in the past where the spec is published but later breaks</span></li><li class="c0 li-bullet-0"><span class="c1">... Build time is part of the PR process that breaks as part of publishing but not later</span></li></ul><p class="c9"><span class="c1"></span></p><ul class="c3 lst-kix_b1qr3pe9lkq6-0"><li class="c5 li-bullet-0"><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://github.com/w3c/performance-timeline/issues/178&amp;sa=D&amp;source=editors&amp;ust=1620034522435000&amp;usg=AOvVaw0RDhQloKY8zJ5n02-YdU07">When should a UA clear its entry buffers?</a></span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-1 start"><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: Context was for PerformanceEventTiming</span></li><li class="c0 li-bullet-0"><span class="c1">... We always buffer timing entries if they have more than 100ms</span></li><li class="c0 li-bullet-0"><span class="c1">... That will grow indefinitely, should the UA be able to clear entry buffers at some point</span></li><li class="c0 li-bullet-0"><span class="c1">... Days-old entry buffers are probably not going to be helpful anymore</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Resource timing has the ability to explicitly clear buffers, as well as offering an overall buffer limit.</span></li><li class="c0 li-bullet-0"><span class="c1">...this proved to be an antipattern, since multiple scripts on page can think they are done with the data and clear each other..</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: We already have an overall buffer limit of 150. Are you worried about old entries?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: Do we have a limit for Event Timing?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: We do indeed have limits. The reason for the buffers is to get data from early in the page load, until the observers are registered. </span></li><li class="c0 li-bullet-0"><span class="c1">… the current buffer limits are arbitrary, we didn’t really do enough studies to see what the perfect limits would be.</span></li><li class="c0 li-bullet-0"><span class="c1">… once the buffer is full, it doesn’t keep increasing.</span></li><li class="c0 li-bullet-0"><span class="c1">… The expectation is that you would have already registered listeners by then.</span></li><li class="c0 li-bullet-0"><span class="c1">… There is one entry type that has no buffer limit: User Timing, because it is a developer initiated signal. Also we need to support getEntryByName() which don’t have a buffer size limit.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: So is there an expectation that we should be able to clear the buffer?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: Who, the browser?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: Yes.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: That runs the risk of violating developer expectations. I don’t know if developers are collecting UserTiming Entries from many days ago, but they can. Is that main concern a memory concern?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: Memory concern.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: Is this still hypothetical or have you seen it in practice?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: I was thinking of Event Timing, but if it’s limited that may not be an issue. We have seen some cases, like user timing, where it takes lots of memory (maybe it was Facebook, cannot recall exactly)</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Facebook has a separate use case where they want to use User Timing for DevTools and not for perf timeline. </span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: I have some context here, they were adding entries to UT and immediately clear them, so they would show up in Dev Tools. But the entries didn’t persist in the timeline. I don’t know if that removes them from the buffer</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: It should remove them.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: They use lots of timers and others may persist. The use case they discussed was for advanced debugging, but they probably have others.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: So we have buffer limits, other than UT where they have clearMarks and clearMeasures, developer can cleanup those for long-lived apps, either because they want Dev Tools annotation, or because they've collected those marks/measures and they've sent them to their server, so they can be cleared from the buffer.</span></li><li class="c0 li-bullet-0"><span class="c1">... That seems like it would address the developer concern</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: That seems fine</span></li><li class="c0 li-bullet-0"><span><b>Nic</b>: We have </span><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://w3c.github.io/timing-entrytypes-registry/&amp;sa=D&amp;source=editors&amp;ust=1620034522437000&amp;usg=AOvVaw2cWbFetXQNm-FZY2WV6bkk">Timing Entry Names Registry</a></span><span class="c1">&nbsp;where we can change the max buffer sizes if we need to, either increases if they're too egregious or too small (e.g. ResourceTiming increased from 150 to 250)</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: We should implement the “number of dropped entries”, which we specified</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: that would enable us to know if our limits are too small.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: Sounds like the intention of the buffer is to be a bootstrapping buffer for late observers. If you haven’t registered your buffers and you have many dropped entries, is it worthwhile at this point to still keep those entries? The measurement is already tainted.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: Can talk about Resource Timing. It was defined as 150 entries, we often found customers with waterfalls that didn’t include all the entries, and often had to bump the buffer size for them. But having a partial result was way better than having no result. My preference would be to present whatever you can and say how many were dropped. Understand the memory concerns.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: If you could drop timeline data from pages that are no longer relevant, would you have more room for keeping entries on the current page?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: Something to keep in mind that adding an auto-clearing heuristic might cause issues to those looking at the data</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Tradeoff between memory utilization and consistency</span></li><li class="c0 li-bullet-0"><span class="c1">... Because those buffers are bound to what seem like reasonable values, I wouldn't expect dropping them would gain you a ton of memory</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: In the absence of numDroppedEntries having predictable fixed numbers for buffers is important (or else you don’t know when buffer is full), but I wonder if once that is added we cannot have flexible buffer sizes? The buffer limits were apparently arbitrarily picked.</span></li><li class="c0 li-bullet-0"><span class="c1">… Sean - were your questions addressed?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Sean</b>: Yes</span></li></ul><p class="c9 c10"><span class="c1"></span></p><ul class="c3 lst-kix_b1qr3pe9lkq6-0"><li class="c5 li-bullet-0"><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://github.com/w3c/preload/issues/157&amp;sa=D&amp;source=editors&amp;ust=1620034522438000&amp;usg=AOvVaw2SapRyw70gfmJzSp-0sgmr">Allow HTTP headers to be defined for the preload request</a></span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-1 start"><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Issue we talked about many years ago as part of Fetch parameters</span></li><li class="c0 li-bullet-0"><span class="c1">... Essentially what Angular folks are trying to do is Preload Fetch requests that are being sent later</span></li><li class="c0 li-bullet-0"><span class="c1">... They're being fitted with custom Accept headers, e.g. JSON over XML for various REST API endpoints</span></li><li class="c0 li-bullet-0"><span class="c1">... Because of those custom Accept headers, right unspecified Preload cache in Chromium and Webkit doesn't match those requests, and when they're later calling Fetch they're triggering a second request. &nbsp;That's the desired behavior here because if Preload cache were to match requests with different headers they could have different responses</span></li><li class="c0 li-bullet-0"><span class="c1">... So Preload cache behavior here seems correct even though it's not specified</span></li><li class="c0 li-bullet-0"><span class="c1">... No way to trigger Preload without double-download</span></li><li class="c0 li-bullet-0"><span class="c1">... Ideally what they'd like is an attribute on Preload to specify Accept header or any arbitrary on the request</span></li><li class="c0 li-bullet-0"><span class="c1">... On one hand I think the use-case is legit, but I'm concerned about adding cruft to HTML</span></li><li class="c0 li-bullet-0"><span class="c1">... In the past we've asked about adding Fetch object attributes to elements that load resources, so they could specify a JSON with the various Fetch options to apply to the resource request, to define new headers or other parameters, credentialed mode, etc</span></li><li class="c0 li-bullet-0"><span class="c1">... At the same time I'm concerned about adding arbitrary cruft</span></li><li class="c0 li-bullet-0"><span class="c1">... Tradeoff between HTML legibility and Preload for those use-cases</span></li><li class="c0 li-bullet-0"><span class="c1">... We can continue discussions on issue itself</span></li><li class="c0 li-bullet-0"><span class="c1">... AI: Yoav to respond on issue</span></li></ul><p class="c9 c10"><span class="c1"></span></p><ul class="c3 lst-kix_b1qr3pe9lkq6-0"><li class="c5 li-bullet-0"><span class="c6"><a class="c2" href="https://www.google.com/url?q=https://github.com/w3c/preload/issues/156&amp;sa=D&amp;source=editors&amp;ust=1620034522439000&amp;usg=AOvVaw2cNsLVvYkFtkhqDKwTI0Ab">Can't preload for type-switching &lt;picture&gt;s</a></span></li></ul><ul class="c3 lst-kix_b1qr3pe9lkq6-1 start"><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: When using &lt;picture&gt; to load new and exciting image formats that are not yet supported anywhere, we currently have a way to use the type attribute to just Preload the latest one.</span></li><li class="c0 li-bullet-0"><span class="c1">... That worked well with WebP, but if we're interested in Preloading more than just the latest format, i.e. AVIF has support in some browsers. &nbsp;Preload AVIF and WebP and JPEG-XL, it's becoming a problem to only use the correct one.</span></li><li class="c0 li-bullet-0"><span class="c1">... Want to be able to Preload AVIF, if you don't support AVIF Preload WebP, if not JPEG, etc</span></li><li class="c0 li-bullet-0"><span class="c1">... We avoided tackling this use-case in the past because it didn't seem like it had a lot of real-life implications, and support matrix for newer formats matched Preload, but with AVIF and more common Preload support, it seems like there is now a mechanism</span></li><li class="c0 li-bullet-0"><span class="c1">... Opinions on what that may look like?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: Do you want to tie multiple preloads together?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Yes, but we can’t really add a new element to the head. And we can’t use &lt;link&gt; for that, because link is self closing.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: If they all shared a common ID?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: That would be one way of doing that, but not sure that the processing model for that would be reasonable. E.g. multiple links in the head and another that arrives later. May work if we still take ordering into account.</span></li><li class="c0 li-bullet-0"><span class="c1">… What do folks think about the use case? A reasonable one for us to tackle?</span></li><li class="c0 li-bullet-0"><span class="c1">... We had similar requests in past for fonts which were dismissed by hoping all UAs would just support WOFF2</span></li><li class="c0 li-bullet-0"><span class="c1">... But with progressively rendered webfonts, the same mechanism could potentially be useful for both</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: Why can't you have rel=preload inside &lt;picture&gt; element sources?</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Preload is typically you'd put before something is defined, i.e. when picture is dynamically generated or added later on</span></li><li class="c0 li-bullet-0"><span class="c1">... You would want to Preload that image in those cases</span></li><li class="c0 li-bullet-0"><span class="c1">... If you're already discovering the Picture element and the images inside it, there's no difference between loading and preloading it</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nic</b>: would you be able to define picture twice, with only links in it and no images? You’d define it twice, I guess.</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Michal</b>: Or a hidden picture</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Nicol&aacute;s</b>: In that guess picture becomes a link so better to just add that link </span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Another thing to bare in mind - whatever we come up with should also work in HTTP Header format for Link</span></li><li class="c0 li-bullet-0"><span class="c1">... So maybe instead of an ID that requires a cache across elements or headers</span></li><li class="c0 li-bullet-0"><span class="c1">... Instead have a "not-type" attribute, i.e. this is a WebP but don't load it if you support AVIF, load this JPEG If you don't support neither AVIF nor WebP</span></li><li class="c0 li-bullet-0"><span class="c1">… Maybe cumbersome, but expressive</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Benjamin</b>: What you said sounds more like a header, where you put Preload priority in this order</span></li><li class="c0 li-bullet-0"><span class="c1"><b>Yoav</b>: Main conclusion is that we need to explore this more, multiple possible sketches and none is ideal</span></li><li class="c0 li-bullet-0"><span>... Take to the issue and discuss further there</span></li></ul></div></div><div id="footer"><span>Published by <a target="_blank" title="Learn more about Google Drive" href="https://docs.google.com/">Google Drive</a></span><span class="dash">–</span><a href="https://docs.google.com/u/0/abuse?id=AKkXjoyuXSEoDY49zf8XfV3Jvcq7LtAaHML9aek7AU7wHsC3b5Xx02AkHI0KTceqoIDXoM6_peiFoD4-fj2NtVc:0">Report Abuse</a></div><script type="text/javascript" nonce="">(function(){/*

 Copyright The Closure Library Authors.
 SPDX-License-Identifier: Apache-2.0
*/
var aa="function"==typeof Object.create?Object.create:function(a){function b(){}b.prototype=a;return new b},ba="function"==typeof Object.defineProperties?Object.defineProperty:function(a,b,c){if(a==Array.prototype||a==Object.prototype)return a;a[b]=c.value;return a};
function ca(a){a=["object"==typeof globalThis&&globalThis,a,"object"==typeof window&&window,"object"==typeof self&&self,"object"==typeof global&&global];for(var b=0;b<a.length;++b){var c=a[b];if(c&&c.Math==Math)return c}throw Error("Cannot find global object");}var da=ca(this);function ea(a,b){if(b)a:{var c=da;a=a.split(".");for(var d=0;d<a.length-1;d++){var e=a[d];if(!(e in c))break a;c=c[e]}a=a[a.length-1];d=c[a];b=b(d);b!=d&&null!=b&&ba(c,a,{configurable:!0,writable:!0,value:b})}}var h;
if("function"==typeof Object.setPrototypeOf)h=Object.setPrototypeOf;else{var l;a:{var fa={a:!0},ha={};try{ha.__proto__=fa;l=ha.a;break a}catch(a){}l=!1}h=l?function(a,b){a.__proto__=b;if(a.__proto__!==b)throw new TypeError(a+" is not extensible");return a}:null}var ia=h;
function m(a,b){a.prototype=aa(b.prototype);a.prototype.constructor=a;if(ia)ia(a,b);else for(var c in b)if("prototype"!=c)if(Object.defineProperties){var d=Object.getOwnPropertyDescriptor(b,c);d&&Object.defineProperty(a,c,d)}else a[c]=b[c];a.m=b.prototype}ea("Object.is",function(a){return a?a:function(b,c){return b===c?0!==b||1/b===1/c:b!==b&&c!==c}});var q=this||self;function r(){}function t(a){var b=typeof a;return"object"==b&&null!=a||"function"==b}
function ja(a,b){var c=Array.prototype.slice.call(arguments,1);return function(){var d=c.slice();d.push.apply(d,arguments);return a.apply(this,d)}}function ka(a,b){function c(){}c.prototype=b.prototype;a.m=b.prototype;a.prototype=new c;a.prototype.constructor=a;a.A=function(d,e,f){for(var g=Array(arguments.length-2),k=2;k<arguments.length;k++)g[k-2]=arguments[k];return b.prototype[e].apply(d,g)}}function u(a){return a};function w(a){w[" "](a);return a}w[" "]=r;function la(a,b,c){return Object.prototype.hasOwnProperty.call(a,b)?a[b]:a[b]=c(b)};function ma(a){return la(a.prototype,"$$generatedClassName",function(){return"Class$obf_"+{valueOf:function(){return++na}}})}var na=1E3;function x(){}x.prototype.s=function(){return this.j||(Object.defineProperties(this,{j:{value:oa=oa+1|0,enumerable:!1}}),this.j)};x.prototype.toString=function(){var a=y(z(pa(this.constructor)))+"@";var b=(this.s()>>>0).toString(16);return a+y(b)};function A(){}m(A,x);A.prototype.i=function(a){this.h=a;if(a instanceof Object)try{a.v=this}catch(b){}};function qa(a){a.h instanceof Error&&(Error.captureStackTrace?Error.captureStackTrace(a.h):a.h.stack=Error().stack)}A.prototype.toString=function(){var a=z(pa(this.constructor)),b=this.l;return null==b?a:y(a)+": "+y(b)};function B(){}m(B,A);function D(){}m(D,B);function E(){}m(E,D);E.prototype.i=function(a){D.prototype.i.call(this,Object.is(this.g,"__noinit__")?a:this.g)};function ra(){}m(ra,E);function sa(a,b){return"string"==typeof a?a.charCodeAt(b):a.g(b)};var oa=0;function y(a){return null==a?"null":a.toString()}function ta(a){return 65536<=a?y(String.fromCharCode((55296+((a-65536|0)>>10&1023)|0)&65535))+y(String.fromCharCode((56320+((a-65536|0)&1023)|0)&65535)):String.fromCharCode(a&65535)}function ua(a,b){var c=b,d=a.length,e;b=sa(a,(e=c,c=c+1|0,e));var f;if(e=55296<=b&&56319>=b&&c<d)a=f=sa(a,c),e=56320<=a&&57343>=a;var g;e?g=65536+((b&1023)<<10)+(f&1023)|0:g=b;return g};function F(a,b){this.h=a;this.g=b}m(F,x);function z(a){var b=ma(a.h);0!=a.g&&(b="L"+y(b)+";");a=a.g;for(var c="",d=0;d<a;d=d+1|0)c=y(c)+"[";return y(c)+y(b)}F.prototype.toString=function(){return"class "+y(z(this))};function pa(a){return la(a.prototype,"$$class/0",function(){return new F(a,0)})};function G(a,b){return null==a?a:b?decodeURI(a):decodeURIComponent(a)};var va=/^(?:([^:/?#.]+):)?(?:\/\/(?:([^/?#]*)@)?([^/#?]*?)(?::([0-9]+))?(?=[/#?]|$))?([^?#]+)?(?:\?([^#]*))?(?:#([\S\s]*))?$/;function wa(a){a=va.exec(a);for(var b=[],c=0;7>=c;c=c+1|0)a.length<=c||null==a[c]?b.push(null):b.push(a[c]);return b}
function xa(a,b){var c=a.indexOf(ta(35));c=0>c?a.length:c;a:{var d=0;for(var e=b.length;0<(d=a.indexOf(b,d))&&d<c;){var f=ua(a,d-1|0);if(38==f||63==f){if((d+e|0)>=a.length)break a;f=ua(a,d+e|0);if(61==f||38==f||35==f)break a}d=d+(e+1)|0}d=-1}if(0>d)return null;e=a.indexOf(ta(38),d);if(0>e||e>c)e=c;d=d+(b.length+1)|0;b=Math.min(a.length,d);a=a.substr(b,Math.min(a.length,Math.max(d,e))-b|0);c=" ";for(b=0;0<=(b=c.indexOf("\\",b));)36==c.charCodeAt(b+1|0)?(d=y(c.substr(0,b|0))+"$",e=b=b+1|0,c=d+y(c.substr(e))):
(d=y(c.substr(0,b|0)),e=b=b+1|0,c=d+y(c.substr(e)));a=a.replace(/\+/g,c);return G(a,!1)};function ya(a){a&&"function"==typeof a.u&&a.u()};function H(){this.h=this.h;this.g=this.g}H.prototype.h=!1;H.prototype.u=function(){this.h||(this.h=!0,this.j())};H.prototype.j=function(){if(this.g)for(;this.g.length;)this.g.shift()()};var za=Array.prototype.indexOf?function(a,b){return Array.prototype.indexOf.call(a,b,void 0)}:function(a,b){if("string"===typeof a)return"string"!==typeof b||1!=b.length?-1:a.indexOf(b,0);for(var c=0;c<a.length;c++)if(c in a&&a[c]===b)return c;return-1};var Aa=/&/g,Ba=/</g,Ca=/>/g,Da=/"/g,Ea=/'/g,Fa=/\x00/g,Ga=/[\x00&<>"']/;var I;a:{var Ha=q.navigator;if(Ha){var Ia=Ha.userAgent;if(Ia){I=Ia;break a}}I=""}function J(a){return-1!=I.indexOf(a)};function Ja(a,b,c){for(var d in a)b.call(c,a[d],d,a)};var K;function L(a,b){this.i=a===Ka&&b||"";this.j=La}L.prototype.h=!0;L.prototype.g=function(){return this.i};var La={},Ka={};function M(a,b){this.i=b===N?a:""}M.prototype.h=!0;M.prototype.g=function(){return this.i.toString()};M.prototype.toString=function(){return this.i.toString()};function O(a){return a instanceof M&&a.constructor===M?a.i:"type_error:SafeUrl"}
var Ma=/^(?:audio\/(?:3gpp2|3gpp|aac|L16|midi|mp3|mp4|mpeg|oga|ogg|opus|x-m4a|x-matroska|x-wav|wav|webm)|font\/\w+|image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp|x-icon)|video\/(?:mpeg|mp4|ogg|webm|quicktime|x-matroska))(?:;\w+=(?:\w+|"[\w;,= ]+"))*$/i,Na=/^data:(.*);base64,[a-z0-9+\/]+=*$/i,Oa=/^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i;function Pa(a){if(a instanceof M)return a;a="object"==typeof a&&a.h?a.g():String(a);Oa.test(a)||(a="about:invalid#zClosurez");return new M(a,N)}
var N={},Qa=new M("about:invalid#zClosurez",N);function P(a,b,c){this.i=c===Ra?a:""}P.prototype.h=!0;P.prototype.g=function(){return this.i.toString()};P.prototype.toString=function(){return this.i.toString()};var Ra={};function Sa(a,b,c,d){a=a instanceof M?a:Pa(a);b=b||q;c=c instanceof L?c instanceof L&&c.constructor===L&&c.j===La?c.i:"type_error:Const":c||"";return void 0!==d?b.open(O(a),c,d,void 0):b.open(O(a),c)};var Ta=J("Trident")||J("MSIE"),Ua=J("Edge")||Ta,Va=J("Gecko")&&!(-1!=I.toLowerCase().indexOf("webkit")&&!J("Edge"))&&!(J("Trident")||J("MSIE"))&&!J("Edge"),Wa=J("Macintosh");var Xa=function(){if(!q.addEventListener||!Object.defineProperty)return!1;var a=!1,b=Object.defineProperty({},"passive",{get:function(){a=!0}});try{q.addEventListener("test",r,b),q.removeEventListener("test",r,b)}catch(c){}return a}();function Q(a,b){this.type=a;this.target=b;this.i=!1}Q.prototype.g=function(){this.i=!0};function R(a){Q.call(this,a?a.type:"");this.relatedTarget=this.target=null;this.button=this.screenY=this.screenX=this.clientY=this.clientX=0;this.key="";this.metaKey=this.shiftKey=this.altKey=this.ctrlKey=!1;this.state=null;this.pointerId=0;this.pointerType="";this.h=null;if(a){var b=this.type=a.type,c=a.changedTouches&&a.changedTouches.length?a.changedTouches[0]:null;this.target=a.target||a.srcElement;var d=a.relatedTarget;if(d){if(Va){a:{try{w(d.nodeName);var e=!0;break a}catch(f){}e=!1}e||(d=null)}}else"mouseover"==
b?d=a.fromElement:"mouseout"==b&&(d=a.toElement);this.relatedTarget=d;c?(this.clientX=void 0!==c.clientX?c.clientX:c.pageX,this.clientY=void 0!==c.clientY?c.clientY:c.pageY,this.screenX=c.screenX||0,this.screenY=c.screenY||0):(this.clientX=void 0!==a.clientX?a.clientX:a.pageX,this.clientY=void 0!==a.clientY?a.clientY:a.pageY,this.screenX=a.screenX||0,this.screenY=a.screenY||0);this.button=a.button;this.key=a.key||"";this.ctrlKey=a.ctrlKey;this.altKey=a.altKey;this.shiftKey=a.shiftKey;this.metaKey=
a.metaKey;this.pointerId=a.pointerId||0;this.pointerType="string"===typeof a.pointerType?a.pointerType:Ya[a.pointerType]||"";this.state=a.state;this.h=a;a.defaultPrevented&&R.m.g.call(this)}}ka(R,Q);var Ya={2:"touch",3:"pen",4:"mouse"};R.prototype.g=function(){R.m.g.call(this);var a=this.h;a.preventDefault?a.preventDefault():a.returnValue=!1};var S="closure_listenable_"+(1E6*Math.random()|0);var Za=0;function $a(a,b,c,d,e){this.listener=a;this.g=null;this.src=b;this.type=c;this.capture=!!d;this.i=e;this.key=++Za;this.h=this.o=!1}function ab(a){a.h=!0;a.listener=null;a.g=null;a.src=null;a.i=null};function T(a){this.src=a;this.g={};this.h=0}T.prototype.add=function(a,b,c,d,e){var f=a.toString();a=this.g[f];a||(a=this.g[f]=[],this.h++);var g;a:{for(g=0;g<a.length;++g){var k=a[g];if(!k.h&&k.listener==b&&k.capture==!!d&&k.i==e)break a}g=-1}-1<g?(b=a[g],c||(b.o=!1)):(b=new $a(b,this.src,f,!!d,e),b.o=c,a.push(b));return b};var U="closure_lm_"+(1E6*Math.random()|0),V={},bb=0;function cb(a,b,c,d,e){if(d&&d.once)return db(a,b,c,d,e);if(Array.isArray(b)){for(var f=0;f<b.length;f++)cb(a,b[f],c,d,e);return null}c=eb(c);return a&&a[S]?a.g(b,c,t(d)?!!d.capture:!!d,e):fb(a,b,c,!1,d,e)}
function fb(a,b,c,d,e,f){if(!b)throw Error("Invalid event type");var g=t(e)?!!e.capture:!!e,k=gb(a);k||(a[U]=k=new T(a));c=k.add(b,c,d,g,f);if(c.g)return c;d=hb();c.g=d;d.src=a;d.listener=c;if(a.addEventListener)Xa||(e=g),void 0===e&&(e=!1),a.addEventListener(b.toString(),d,e);else if(a.attachEvent)a.attachEvent(ib(b.toString()),d);else if(a.addListener&&a.removeListener)a.addListener(d);else throw Error("addEventListener and attachEvent are unavailable.");bb++;return c}
function hb(){function a(c){return b.call(a.src,a.listener,c)}var b=jb;return a}function db(a,b,c,d,e){if(Array.isArray(b)){for(var f=0;f<b.length;f++)db(a,b[f],c,d,e);return null}c=eb(c);return a&&a[S]?a.h(b,c,t(d)?!!d.capture:!!d,e):fb(a,b,c,!0,d,e)}
function kb(a){if("number"!==typeof a&&a&&!a.h){var b=a.src;if(b&&b[S])b.i(a);else{var c=a.type,d=a.g;b.removeEventListener?b.removeEventListener(c,d,a.capture):b.detachEvent?b.detachEvent(ib(c),d):b.addListener&&b.removeListener&&b.removeListener(d);bb--;if(c=gb(b)){d=a.type;if(d in c.g){var e=c.g[d],f=za(e,a),g;(g=0<=f)&&Array.prototype.splice.call(e,f,1);g&&(ab(a),0==c.g[d].length&&(delete c.g[d],c.h--))}0==c.h&&(c.src=null,b[U]=null)}else ab(a)}}}
function ib(a){return a in V?V[a]:V[a]="on"+a}function jb(a,b){if(a.h)a=!0;else{b=new R(b,this);var c=a.listener,d=a.i||a.src;a.o&&kb(a);a=c.call(d,b)}return a}function gb(a){a=a[U];return a instanceof T?a:null}var lb="__closure_events_fn_"+(1E9*Math.random()>>>0);function eb(a){if("function"===typeof a)return a;a[lb]||(a[lb]=function(b){return a.handleEvent(b)});return a[lb]};function W(a){H.call(this);this.l=a;this.i={}}ka(W,H);var mb=[];function nb(a){Ja(a.i,function(b,c){this.i.hasOwnProperty(c)&&kb(b)},a);a.i={}}W.prototype.j=function(){W.m.j.call(this);nb(this)};W.prototype.handleEvent=function(){throw Error("EventHandler.handleEvent not implemented");};function ob(a){H.call(this);this.i=a||document.body;this.l=new W(this);a=ja(ya,this.l);this.h?a():(this.g||(this.g=[]),this.g.push(a));a=this.l;var b=this.i,c=this.s,d="click";Array.isArray(d)||(d&&(mb[0]=d.toString()),d=mb);for(var e=0;e<d.length;e++){var f=cb(b,d[e],c||a.handleEvent,!1,a.l||a);if(!f)break;a.i[f.key]=f}}m(ob,H);
ob.prototype.s=function(a){if(!(0!=a.h.button||Wa&&a.ctrlKey||a.i))for(var b=a.target;b&&b!=this.i;){if(b.tagName&&"a"==b.tagName.toLowerCase()){var c=b.getAttribute("href")||b.getAttributeNS("http://www.w3.org/1999/xlink","href"),d=c;try{var e=wa(c),f;if(f="www.google.com"===G(e[3],!0)){var g=wa(c);f="/url"===G(g[5],!0)}if(f){var k=xa(c,"q");d=k?k:xa(c,"url")}}catch(v){a:{var p=v;if(null!=p){var n=p.v;if(null!=n){v=n;break a}}if(p instanceof TypeError){var C=n=new ra;C.l=y(p);qa(C);n.g="__noinit__";
n.g=p;n.i(new TypeError(n));p=n}else C=n=new E,C.l=y(p),qa(C),n.g="__noinit__",n.g=p,n.i(Error(n)),p=n;v=p}if(!(v instanceof B))throw v.h;}d=null!=d?d:"";if(c!=d){e=void 0;b={target:"_blank",noreferrer:!0};c=window;d instanceof M?f=d:(f="undefined"!=typeof d.href?d.href:String(d),f instanceof M||(f="object"==typeof f&&f.h?f.g():String(f),Oa.test(f)?f=new M(f,N):(f=String(f),f=f.replace(/(%0A|%0D)/g,""),f=(g=f.match(Na))&&Ma.test(g[1])?new M(f,N):null)),f=f||Qa);d=b.target||d.target;g=[];for(e in b)switch(e){case "width":case "height":case "top":case "left":g.push(e+
"="+b[e]);break;case "target":case "noopener":case "noreferrer":break;default:g.push(e+"="+(b[e]?1:0))}e=g.join(",");if((J("iPhone")&&!J("iPod")&&!J("iPad")||J("iPad")||J("iPod"))&&c.navigator&&c.navigator.standalone&&d&&"_self"!=d)e="A",g=document,e=String(e),"application/xhtml+xml"===g.contentType&&(e=e.toLowerCase()),g=e=g.createElement(e),f=f instanceof M?f:Pa(f),g.href=O(f),e.setAttribute("target",d),b.noreferrer&&e.setAttribute("rel","noreferrer"),b=document.createEvent("MouseEvent"),b.initMouseEvent("click",
!0,!0,c,1),e.dispatchEvent(b);else if(b.noreferrer){if(c=Sa("",c,d,e),b=O(f),c){Ua&&-1!=b.indexOf(";")&&(b="'"+b.replace(/'/g,"%27")+"'");c.opener=null;Ga.test(b)&&(-1!=b.indexOf("&")&&(b=b.replace(Aa,"&amp;")),-1!=b.indexOf("<")&&(b=b.replace(Ba,"&lt;")),-1!=b.indexOf(">")&&(b=b.replace(Ca,"&gt;")),-1!=b.indexOf('"')&&(b=b.replace(Da,"&quot;")),-1!=b.indexOf("'")&&(b=b.replace(Ea,"&#39;")),-1!=b.indexOf("\x00")&&(b=b.replace(Fa,"&#0;")));b='<meta name="referrer" content="no-referrer"><meta http-equiv="refresh" content="0; url='+
b+'">';if(void 0===K)if(d=null,(e=q.trustedTypes)&&e.createPolicy){try{d=e.createPolicy("goog#html",{createHTML:u,createScript:u,createScriptURL:u})}catch(v){q.console&&q.console.error(v.message)}K=d}else K=d;b=(d=K)?d.createHTML(b):b;b=new P(b,null,Ra);(c=c.document)&&c.write&&(c.write(b instanceof P&&b.constructor===P?b.i:"type_error:SafeHtml"),c.close())}}else(c=Sa(f,c,d,e))&&b.noopener&&(c.opener=null);a.g();break}}b=b.parentNode}};function pb(a){new ob(a)}
var X=["DOCS_installLinkReferrerSanitizer"],Y=q;X[0]in Y||"undefined"==typeof Y.execScript||Y.execScript("var "+X[0]);for(var Z;X.length&&(Z=X.shift());)X.length||void 0===pb?Y[Z]&&Y[Z]!==Object.prototype[Z]?Y=Y[Z]:Y=Y[Z]={}:Y[Z]=pb;}).call(this);
</script><script type="text/javascript" nonce="">DOCS_installLinkReferrerSanitizer();</script></body></html>